package ${packages.fiscoServiceImpl};

import cn.hutool.core.util.StrUtil;
import ${packages.fiscoConfig}.BlockchainConfig;
import ${packages.fiscoService}.BlockchainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.codec.decode.TransactionDecoderInterface;
import org.fisco.bcos.sdk.transaction.codec.decode.TransactionDecoderService;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "feature.blockchain", name = "enabled", havingValue = "true", matchIfMissing = true)
public class BlockchainServiceImpl implements BlockchainService {

    private final Client client;
    private final AssembleTransactionProcessor transactionProcessor;
    private final BlockchainConfig blockchainConfig;

    @Override
    public String callContract(String methodName, List<Object> params) {
        try {
            TransactionResponse response = transactionProcessor.sendTransactionAndGetResponseByContractLoader(
                    blockchainConfig.getContractName(),
                    blockchainConfig.getContractAddress(),
                    methodName,
                    params
            );
            return response.getTransactionReceipt().getTransactionHash();
        } catch (Exception e) {
            log.error("合约调用失败, 方法: {}, 错误: {}", methodName, e.getMessage());
            return null;
        }
    }

    @Override
    public String queryContract(String methodName, List<Object> params) {
        try {
            TransactionResponse response = transactionProcessor.sendTransactionAndGetResponseByContractLoader(
                    blockchainConfig.getContractName(),
                    blockchainConfig.getContractAddress(),
                    methodName,
                    params
            );
            return response.getValues();
        } catch (Exception e) {
            log.error("合约查询失败, 方法: {}, 错误: {}", methodName, e.getMessage());
            return null;
        }
    }

    @Override
    public TransactionReceipt getTransactionReceipt(String transactionHash) throws Exception {
        return client.getTransactionReceipt(transactionHash).getResult();
    }

    @Override
    public Long getBlockNumber() throws Exception {
        return client.getBlockNumber().getBlockNumber().longValue();
    }

    @Override
    public String decodeTransactionReceipt(TransactionReceipt receipt) throws Exception {
        CryptoSuite cryptoSuite = client.getCryptoSuite();
        TransactionDecoderInterface decoder = new TransactionDecoderService(cryptoSuite);
        String message = decoder.decodeReceiptMessage(receipt.getInput());
        return StrUtil.emptyToDefault(message, "");
    }
}
